package geektime.spring.springbucks.customerservice;

import geektime.spring.springbucks.customerservice.model.Coffee;
import geektime.spring.springbucks.customerservice.support.CustomConnectionKeepAliveStrategy;

import java.net.URI;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@SpringBootApplication
@Slf4j
public class CustomerServiceApplication
        implements ApplicationRunner {

    @Autowired
    private RestTemplate restTemplate;

    public static void main(String[] args) {
        //		SpringApplication.run(CustomerServiceApplication.class, args);
        new SpringApplicationBuilder().sources(CustomerServiceApplication.class).bannerMode(Mode.OFF).web(WebApplicationType.NONE).run(args);
    }

    public HttpComponentsClientHttpRequestFactory requestFactory() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
        connectionManager.setMaxTotal(200);//一次最多接收MaxTotal次请求
        connectionManager.setDefaultMaxPerRoute(20);//某一个服务每次能并行接收的请求数量

        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).evictIdleConnections(30, TimeUnit.SECONDS).disableAutomaticRetries()
                //有 keep-Alive 里面的值,没有的话永久有效
                //      .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                //换成自定义的
                .setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())
                //加入代理
                .setProxy(new HttpHost("127.0.0.1", 8888)).build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        return requestFactory;
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        //  return  new RestTemplate();
        //  return builder.build();
        return builder.setConnectTimeout(Duration.ofMillis(1000)).setReadTimeout(Duration.ofMillis(5000)).requestFactory(this::requestFactory).build();
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        URI uri = UriComponentsBuilder.fromUriString("http://localhost:8080/coffee/?name={name}").build("mocha");
        RequestEntity<Void> req = RequestEntity.get(uri).accept(MediaType.APPLICATION_XML).build();

        ResponseEntity<String> resp = restTemplate.exchange(req, String.class);
        log.info("Response Status:{},Response Headers:{}", resp.getStatusCode(), resp.getHeaders().toString());
        log.info("Coffee:{}", resp.getBody());

        String coffeeUri = "http://localhost:8080/coffee/";
        Coffee request = Coffee.builder().name("Americano").price(Money.of(CurrencyUnit.of("CNY"), 25.00)).build();
        Coffee response = restTemplate.postForObject(coffeeUri, request, Coffee.class);
        log.info("New Coffee:{}", response);

        ParameterizedTypeReference<List<Coffee>> ptr = new ParameterizedTypeReference<List<Coffee>>() {};
        ResponseEntity<List<Coffee>> list = restTemplate.exchange(coffeeUri, HttpMethod.GET, null, ptr);
        list.getBody().forEach(c -> log.info("Coffee:{}", c));

    }
}
